import type { StyleTagOptions } from '../index'
import { logger } from '../../../types/constants'
import { StyleInjectPosition, SYMBOLS } from '../../../types/interfaces'
import { ToolKit } from '../../utils/toolkit'
import { StyleBaseInjector } from '../base'

/**
 * 标准文档样式注入器: 用于普通 DOM 环境的样式注入
 */
export class StandardInjector extends StyleBaseInjector {
  readonly name: string = 'StandardInjector'
  readonly styleTags: Map<string, HTMLStyleElement> = new Map()

  destroy(): void {
    this.styleTags.forEach(style => style.remove())
    this.styleTags.clear()
  }

  createStyleTag(
    id: string,
    content: string,
    options?: StyleTagOptions,
  ): HTMLStyleElement | null {
    const {
      onlyCreate = false,
      allowEmpty = false,
      allowUpdate = true,
    } = options || {}

    const existingStyle = this.getStyleTag(id)
    if (existingStyle) {
      if (allowUpdate) {
        this.updateStyle(id, content, options)
      }
      return existingStyle
    }

    if (!this.checkContentValidity(id, content, onlyCreate, allowEmpty))
      return null

    const style = document.createElement('style')
    style.id = this.generateStyleId(id)

    if (onlyCreate) {
      logger.debug(`[${this.name}] ${SYMBOLS.UI.BOOKMARK} 创建空样式标签: id='${id}'`)
      this.styleTags.set(id, style)
      return style
    }

    style.textContent = this.processStyleContent(content)
    this.injectStyle(style, options)

    return style
  }

  injectStyle(style: HTMLStyleElement, options: StyleTagOptions = {}): boolean {
    const { position = StyleInjectPosition.Last, override = true } = options
    const id = style.id || 'anonymous-style'

    try {
      // 检查是否已存在同 ID 样式
      const existingStyle = this.getStyleTag(id, false)

      if (existingStyle) {
        if (!override) {
          logger.hint(`[${this.name}] 样式已存在且未启用覆盖，跳过注入: id='${id}'`)
          return false
        }
        existingStyle.remove()
        logger.hint(`[${this.name}] ${SYMBOLS.OTHERS.CLEAR} 已移除旧样式: id='${id}'`)
      }

      const firstChild = document.head.firstChild
      const defaultInsertHandler = () => {
        firstChild
          ? document.head.insertBefore(style, firstChild)
          : document.head.appendChild(style)
      }

      // 根据位置注入
      switch (position) {
        case StyleInjectPosition.First:
          defaultInsertHandler()
          break
        case StyleInjectPosition.Last:
          document.head.appendChild(style)
          break
        default:
          defaultInsertHandler()
          break
      }

      this.styleTags.set(id, style)
      ToolKit.ui.style.markBaiduSearchElement(style)
      logger.success(`[${this.name}] ${SYMBOLS.UI.BOOKMARK} 样式注入成功: id='${id}'`)
      return true
    }
    catch (error) {
      logger.error(`[${this.name}] 样式注入失败: id='${id}'`, error)
      return false
    }
  }

  updateStyle(id: string, content: string, options: StyleTagOptions = {}): boolean {
    let style = this.getStyleTag(id)

    if (!style) {
      // 如果样式不存在，创建新的
      style = this.createStyleTag(id, content, options)
      return style !== null
    }

    // 更新现有样式
    style.textContent = this.processStyleContent(content)
    logger.success(`[${this.name}] ${SYMBOLS.UI.BOOKMARK} 样式更新成功: id='${id}'`)
    return true
  }

  getStyleTag(id: string, needsProcessing: boolean = true): HTMLStyleElement | null {
    const styleId = needsProcessing ? this.generateStyleId(id) : id
    return this.styleTags.get(styleId) || document.getElementById(styleId) as HTMLStyleElement
  }

  generateStyleId(id: string): string {
    return `${id}`
  }
}
